import 'package:flutter/material.dart';

import '../file_node.dart';
import '../node_tile.dart';
import '../file_explorer_controller.dart';
import 'package:ideology/shared/widgets/file_explorer/file_explorer_theme_data.dart';

/// 一个无参函数类型，返回一组子节点列表。
///
/// 通常用作“延迟获取子节点”的回调：当需要真正展开时再执行函数体，
/// 以避免在构建阶段就做昂贵的计算或 IO。
typedef GetChildrenFor = List<FileNode> Function();

/// 根据给定的 [node] 与其逻辑路径 [path]，求解（同步地）返回其子节点列表。
///
/// 场景：当外层组件已知如何生成某一节点的直接子级（例如：
/// 通过缓存或内存模型快速求解），可使用该函数立即返回。
typedef ResolveChildren = List<FileNode> Function(FileNode node, String path);

/// # FileExplorerListView
///
/// 文件/目录树的列表视图容器。
/// - 以懒加载 + 控制器状态驱动的方式呈现根节点与其层级结构；
/// - 每一个可视条目由 [NodeTile] 渲染；
/// - 通过一系列回调（选择/打开/删除/重命名/展开）与外部交互；
/// - 样式、行高、动画时长等从 [FileExplorerThemeData] 注入。
///
/// ## 关键点
/// - **不负责持久化或实际文件系统操作**：一切修改行为通过回调上抛；
/// - **不内置状态**：展开/选中/加载中均取自 [FileExplorerController]；
/// - **路径来源**：根层级项的逻辑路径默认为 `node.name`；当 `FileNode.fullPath` 为空且需要实际文件系统路径时，
///   可借助 [realPathResolver] 做“逻辑路径 → 真实路径”的映射。
class FileExplorerListView extends StatelessWidget {
  /// 根节点集合。每个根节点会渲染为列表中的一项，并可递归展开其子节点。
  final List<FileNode> roots;

  /// 外部控制器：包含展开集合、当前选中路径、加载中集合等状态。
  final FileExplorerController ctl;

  /// 主题/样式配置：行高、动画时长、颜色等。
  final FileExplorerThemeData theme;

  /// 传入的滚动控制器，便于外部联动或记录滚动位置。
  final ScrollController scrollController;

  /// 一个“两段式”的子节点获取器：
  ///
  /// - 形参：(node, path) → 返回一个 **无参函数** [GetChildrenFor]；
  /// - 调用时机：真正需要取子节点时再执行该无参函数，做到懒执行；
  ///
  /// 典型用法：
  /// ```dart
  /// getChildren: () => getChildrenFor(node, path)(), // 先构造，再调用
  /// ```
  final GetChildrenFor Function(FileNode node, String path) getChildrenFor;

  /// 直接（同步）解析给定 [node] 的子节点列表。
  ///
  /// 相较于 [getChildrenFor] 的懒执行，此回调会在调用处立即返回结果。
  final ResolveChildren resolveChildren;

  /// 展开/折叠节点时触发。外部可在此进行异步加载子节点等操作。
  /// - [node]：当前节点
  /// - [path]：当前节点的逻辑路径
  final Future<void> Function(FileNode node, String path) onToggle;

  /// 选中节点时触发（通常只更新控制器里的 selectedPath）。
  /// - [path]：被选中的逻辑路径
  /// - [node]：对应节点数据
  final void Function(String path, FileNode node) onSelect;

  /// 打开节点时触发（文件/目录均可自定义行为）。
  /// - [path]：要打开的逻辑路径
  /// - [node]：对应节点数据
  final void Function(String path, FileNode node) onOpen;

  /// 删除节点时触发。由外部决定删除逻辑与 UI 刷新。
  /// - [path]：要删除的逻辑路径
  /// - [node]：对应节点数据
  final Future<void> Function(String path, FileNode node) onDelete;

  /// 重命名回调。**返回 `true` 表示成功**。
  /// - [path]：当前逻辑路径
  /// - [node]：对应节点
  /// - [newName]：新名称（不含路径）
  ///
  /// 外部可在此进行校验、真实文件系统改名、状态刷新等。
  final Future<bool> Function(String path, FileNode node, String newName) onRename;

  /// 传入文件名，返回用于渲染该文件的颜色。
  ///
  /// 常用于根据扩展名高亮标识，如：`.dart`、`.md` 等。
  final Color Function(String fileName) fileColorResolver;

  /// 将 UI 逻辑路径映射到真实文件系统路径（当 [FileNode.fullPath] 为空时使用）。
  ///
  /// 某些场景下，树节点的 `name`/逻辑路径与真实路径并不一致：
  /// - 例如：虚拟项目树、工作区映射、别名挂载等；
  /// - 外部可通过该回调统一做路径转换。
  final String Function(String logicalPath, FileNode node)? realPathResolver;

  /// 构造函数
  ///
  /// **注意**：本组件不持有内部状态；所有动作（展开、选择、打开、删除、重命名）
  /// 均通过回调上抛，并由外部的 [FileExplorerController] 驱动 UI。
  const FileExplorerListView({
    super.key,
    required this.roots,
    required this.ctl,
    required this.theme,
    required this.scrollController,
    required this.getChildrenFor,
    required this.resolveChildren,
    required this.onToggle,
    required this.onSelect,
    required this.onOpen,
    required this.onDelete,
    required this.onRename,
    required this.fileColorResolver,
    this.realPathResolver,
  });

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      controller: scrollController,
      itemCount: roots.length,
      itemBuilder: (context, index) {
        // 取出当前根节点
        final node = roots[index];

        // 根层级的逻辑路径取 node.name（注意：如需真实路径，可在下游使用 realPathResolver）
        final path = node.name;

        // 从控制器读取展开/选中/加载中的状态
        final expanded = ctl.expanded.value.contains(path);
        final selected = ctl.selectedPath.value == path;
        final isLoading = ctl.loading.value.contains(path);

        // 使用 NodeTile 渲染单个节点；其内部可递归渲染子节点。
        return NodeTile(
          node: node,
          depth: 0, // 根层级深度为 0
          path: path,
          expanded: expanded,
          selected: selected,
          isLoading: isLoading,

          // 懒获取子节点：先用 (node, path) 生成无参函数，再真正执行以获得列表
          getChildren: () => getChildrenFor(node, path)(),

          // 直接解析子节点：适合已有缓存或无需异步的场景
          resolveChildren: resolveChildren,

          // 交互回调（由外部实现具体逻辑）
          onToggle: onToggle,
          onSelect: onSelect,
          onOpen: onOpen,
          onDelete: onDelete,
          onRename: onRename, // 透传重命名回调

          // 提供给 NodeTile 的工具函数 & 状态值
          isExpanded: (p) => ctl.expanded.value.contains(p),
          selectedPath: ctl.selectedPath.value,

          // 外观/动画相关
          theme: theme,
          fileColorResolver: fileColorResolver,
          rowHeight: theme.rowHeight,
          animDuration: theme.animationDuration,

          // 逻辑路径 → 真实路径的可选映射器
          realPathResolver: realPathResolver,
        );
      },
    );
  }
}
